package spacegame.main;

import java.io.IOException;
import java.io.InputStream;

import org.andengine.engine.camera.BoundCamera;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl;
import org.andengine.engine.camera.hud.controls.BaseOnScreenControl;
import org.andengine.engine.camera.hud.controls.AnalogOnScreenControl.IAnalogOnScreenControlListener;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.scene.background.RepeatingSpriteBackground;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.util.FPSLogger;
import org.andengine.extension.physics.box2d.PhysicsConnector;
import org.andengine.extension.physics.box2d.PhysicsFactory;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.extension.physics.box2d.util.Vector2Pool;
import org.andengine.input.sensor.acceleration.AccelerationData;
import org.andengine.input.sensor.acceleration.IAccelerationListener;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.TextureManager;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.atlas.bitmap.source.AssetBitmapTextureAtlasSource;
import org.andengine.opengl.texture.bitmap.BitmapTexture;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.adt.io.in.IInputStreamOpener;
import org.andengine.util.debug.Debug;
import org.andengine.util.math.MathUtils;

import android.annotation.SuppressLint;
import android.hardware.SensorManager;
import android.opengl.GLES20;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.MassData;

/**
 *
 * @author Muiota Betarho
 * @since 18:47:08 - 15.09.2012
 */
public class LevelEditor extends SimpleBaseGameActivity implements IAccelerationListener, IOnSceneTouchListener {
	// ===========================================================
	// Constants
	// ===========================================================

	protected static final int m_worldSize = 128;
	protected static final int CAMERA_WIDTH = 480;
	protected static final int CAMERA_HEIGHT = 320;

	private Scene mScene;

	protected ITextureRegion m_marsTextureRegion;
	protected ITextureRegion m_venusTextureRegion;
	protected ITextureRegion m_jupiterTextureRegion;

	protected PhysicsWorld mPhysicsWorld;

	private int mFaceCount = 0;
	
	
	private ITextureRegion m_onScreenControlBaseTextureRegion;
	private ITextureRegion mOnScreenControlKnobTextureRegion;
	private BitmapTextureAtlas m_onScreenControlTexture;
	//private Camera m_camera;
	private Body m_testbody;
	private ITextureRegion m_spaceshipTextureRegion;
	private BoundCamera mBoundChaseCamera;
	private RepeatingSpriteBackground mRepeatingBackground;

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	public EngineOptions onCreateEngineOptions() {
		//Toast.makeText(this, "Touch the screen to add objects.", Toast.LENGTH_LONG).show();

		//this.m_camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		//-CAMERA_WIDTH*64, -CAMERA_HEIGHT*64, CAMERA_WIDTH*129, 2
		//this.mBoundChaseCamera = new BoundCamera(0, 0, CAMERA_WIDTH , CAMERA_HEIGHT , 0, CAMERA_WIDTH, 0, CAMERA_HEIGHT)
		this.mBoundChaseCamera = new BoundCamera(0 , 0, CAMERA_WIDTH , CAMERA_HEIGHT);

		return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mBoundChaseCamera);
	}

	@Override
	public void onCreateResources() {
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");							
		this.m_marsTextureRegion = loadTexture("gfx/mars_planet.png", this.getTextureManager());
		this.m_venusTextureRegion  =loadTexture("gfx/venus_planet.png", this.getTextureManager());
		this.m_jupiterTextureRegion  =loadTexture("gfx/jupiter_planet.png", this.getTextureManager());
		this.m_spaceshipTextureRegion  =loadTexture("gfx/spaceship.png", this.getTextureManager());
		
		
		//�������� ������� �������� ����������
		this.m_onScreenControlTexture = new BitmapTextureAtlas(this.getTextureManager(), 256, 128, TextureOptions.BILINEAR);
		this.m_onScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.m_onScreenControlTexture, this, "onscreen_control_base.png", 0, 0);
	//	this.mOnScreenControlBaseTextureRegion.setTextureSize(this.mOnScreenControlBaseTextureRegion.getWidth()*2, this.mOnScreenControlBaseTextureRegion.getHeight()*2);
		this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.m_onScreenControlTexture, this, "onscreen_control_knob.png", 128, 0);
		this.m_onScreenControlTexture.load();
		
		
		this.mRepeatingBackground = new RepeatingSpriteBackground(CAMERA_WIDTH*(m_worldSize*2+1),CAMERA_HEIGHT*(m_worldSize*2+1), this.getTextureManager(),
				AssetBitmapTextureAtlasSource.create(this.getAssets(), "gfx/backgroundstars.jpg"), this.getVertexBufferObjectManager());

		//this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 512, 512, TextureOptions.BILINEAR);
		//this.mBoxFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "earth_planet.png", 0, 0, 1, 2); // 64x32
	//	this.mCircleFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "mars_planet.png", 0, 256, 1, 2); // 64x32
	//	this.mBitmapTextureAtlas.load();
	}

	
	


	@Override
	public Scene onCreateScene() {
		this.mEngine.registerUpdateHandler(new FPSLogger());

		this.mScene = new Scene();
		this.mScene.setBackground(new Background(0, 0, 0));
		this.mScene.setOnSceneTouchListener(this);

		this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);

		final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
		//Bounds of world
		final Rectangle ground = new Rectangle(-CAMERA_WIDTH*m_worldSize, CAMERA_HEIGHT*(m_worldSize+1) - 2, CAMERA_WIDTH*(m_worldSize*2+1), 2, vertexBufferObjectManager);
		final Rectangle roof = new Rectangle(-CAMERA_WIDTH*m_worldSize, -CAMERA_HEIGHT*m_worldSize, CAMERA_WIDTH*(m_worldSize*2+1), 2, vertexBufferObjectManager);
		final Rectangle left = new Rectangle(-CAMERA_WIDTH*m_worldSize, -CAMERA_HEIGHT*m_worldSize, 2, CAMERA_HEIGHT*(m_worldSize*2+1), vertexBufferObjectManager);
		final Rectangle right = new Rectangle(CAMERA_WIDTH*(m_worldSize+1) - 2, - CAMERA_HEIGHT*m_worldSize, 2, CAMERA_HEIGHT*(m_worldSize*2+1), vertexBufferObjectManager);

		final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);

		this.mScene.attachChild(ground);
		this.mScene.attachChild(roof);
		this.mScene.attachChild(left);
		this.mScene.attachChild(right);

		this.mScene.registerUpdateHandler(this.mPhysicsWorld);

		//Set scene gravity
		final Vector2 _gravity = Vector2Pool.obtain(0, 0);
		this.mPhysicsWorld.setGravity(_gravity);
		Vector2Pool.recycle(_gravity);
		
			 
		Sprite repeatingSprite = this.mRepeatingBackground.getSprite();
		repeatingSprite.setPosition(-CAMERA_WIDTH*64, -CAMERA_HEIGHT*64);
		this.mScene.attachChild(repeatingSprite);
		
		this.initOnScreenControls();
	
		//Create main ship
		Sprite _face = new Sprite(CAMERA_WIDTH/2, CAMERA_HEIGHT/2, this.m_spaceshipTextureRegion, this.getVertexBufferObjectManager());
		_face.setScale(0.5f);
		final FixtureDef _objectFixtureDef = PhysicsFactory.createFixtureDef( 1f, 0.3f, 1f);
		Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, _face, BodyType.DynamicBody, _objectFixtureDef);

		this.mScene.attachChild(_face);
		this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(_face, body, true, true));
	    this.m_testbody = body;
		this.mBoundChaseCamera.setChaseEntity(_face);
		
		
		this.mBoundChaseCamera.setBoundsEnabled(false);
		
		
		//this.mBoundChaseCamera.set(0, 0, CAMERA_WIDTH , CAMERA_HEIGHT);
		return this.mScene;
	}

	@Override
	public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
		if(this.mPhysicsWorld != null) {
			if(pSceneTouchEvent.isActionDown()) {
				this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
				return true;
			}
		}
		return false;
	}

	@Override
	public void onAccelerationAccuracyChanged(final AccelerationData pAccelerationData) {

	}

	@Override
	public void onAccelerationChanged(final AccelerationData pAccelerationData) {
		
	}

	@Override
	public void onResumeGame() {
		super.onResumeGame();

		this.enableAccelerationSensor(this);
	}

	@Override
	public void onPauseGame() {
		super.onPauseGame();
		this.disableAccelerationSensor();
	}

	// ===========================================================
	// Methods
	// ===========================================================

	private void addFace(final float pX, final float pY) {
		this.mFaceCount++;
		Debug.d("Faces: " + this.mFaceCount);

		final Sprite face;
		final Body body;

		final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef( 1f, 0.3f, 1f);

		if(this.mFaceCount % 3 == 0) {
			face = new Sprite(pX, pY, this.m_marsTextureRegion, this.getVertexBufferObjectManager());
			face.setScale(MathUtils.random(0.4f, 1f));
			body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
		} else if(this.mFaceCount % 3 == 1)  {
			face = new Sprite(pX, pY, this.m_venusTextureRegion, this.getVertexBufferObjectManager());
			face.setScale(MathUtils.random(0.4f, 1f));
			body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
		
	}
		else {
			face = new Sprite(pX, pY, this.m_jupiterTextureRegion, this.getVertexBufferObjectManager());
			face.setScale(MathUtils.random(0.4f, 1f));
			body = PhysicsFactory.createCircleBody (this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
		}
		//face.animate(200);

		this.mScene.attachChild(face);
		
		final MassData data = body.getMassData();
		data.mass = 10000;	
		data.I = 10000;
		body.setMassData(data);
		
		this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
	
	}

	//For load texture method
	private final ITextureRegion loadTexture(final String path, TextureManager textureManager ) {
		try {
			
			final BitmapTexture _bitmapTexture = new BitmapTexture(textureManager, new IInputStreamOpener() {
				
				@Override
				public InputStream open() throws IOException {
					return getAssets().open(path);
				}
			});
			_bitmapTexture.load();
			final ITextureRegion _textureRegion = TextureRegionFactory.extractFromTexture(_bitmapTexture);
			return _textureRegion;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	//Make screen controls
	@SuppressLint({ "FloatMath", "FloatMath" })
	private void initOnScreenControls() {
		final AnalogOnScreenControl analogOnScreenControl = new AnalogOnScreenControl(0, 
				CAMERA_HEIGHT - this.m_onScreenControlBaseTextureRegion.getHeight(), 
				this.mBoundChaseCamera, this.m_onScreenControlBaseTextureRegion, 
				this.mOnScreenControlKnobTextureRegion, 0.1f, 
				this.getVertexBufferObjectManager(), new IAnalogOnScreenControlListener() {
			@Override
			public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
				//final Body carBody = RacerGameActivity.this.mCarBody;
			
				
			if (m_testbody != null)
			{	 
				final float _theta = (float)(m_testbody.getAngle() + Math.PI*0.5);		
				final float _deltax = (float) (Math.cos(_theta));
				final float _deltay = (float) (Math.sin(_theta));
				
				final float _yRadius =  pValueY * 50;
				final Vector2 _thrustVelocity = Vector2Pool.obtain(_yRadius*_deltax , _yRadius*_deltay );
				final float _xRadius =  pValueX * 10;
				final Vector2 _tieRodVelocity = Vector2Pool.obtain(_xRadius*_deltay , -_xRadius*_deltax );
	
				
				
			final Vector2 _bodyCenter = m_testbody.getWorldCenter();
			final Vector2 _tieCenter =  Vector2Pool.obtain(_bodyCenter.x-_deltax*4,_bodyCenter.y-_deltay*4) ;
			final MassData _bodyMassData = m_testbody.getMassData();
			_bodyMassData.mass = 10;
			_bodyMassData.I = 10;
			
			m_testbody.setMassData(_bodyMassData);
			//engine thrust
			m_testbody.applyForce(_thrustVelocity, _bodyCenter);
			m_testbody.applyForce(_tieRodVelocity, _tieCenter);
			/*float _angularImpulse = pValueX * 2;
			if (_angularImpulse > 0.4 || _angularImpulse < -0.4)
				m_testbody.applyAngularImpulse(_angularImpulse);*/
			
			}
		//	m_testbody.setLinearVelocity (velocity);}
				//	carBody.setLinearVelocity(velocity);
			//	Vector2Pool.recycle(_velocity);

			//	final float _rotationInRad = (float)Math.atan2(-pValueX, pValueY);
			//	carBody.setTransform(carBody.getWorldCenter(), rotationInRad);

			//	RacerGameActivity.this.mCar.setRotation(MathUtils.radToDeg(rotationInRad));
			}

			@Override
			public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
				/* Nothing. */
			}
		});
		analogOnScreenControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
		analogOnScreenControl.getControlBase().setAlpha(0.5f);
		//		analogOnScreenControl.getControlBase().setScaleCenter(0, 128);
		//		analogOnScreenControl.getControlBase().setScale(0.75f);
		//		analogOnScreenControl.getControlKnob().setScale(0.75f);
		analogOnScreenControl.refreshControlKnobPosition();

		this.mScene.setChildScene(analogOnScreenControl);
	}
	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
}
